package com.example.userservice.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.userservice.common.UserContext;
import com.example.userservice.entity.Detail;
import com.example.userservice.entity.Log;
import com.example.userservice.entity.User;
import com.example.userservice.entity.dto.UserDtoUpdate;
import com.example.userservice.entity.dto.UserDto;
import com.example.userservice.entity.dto.UserDtoRegisterOrLogin;
import com.example.userservice.entity.dto.UserDtoRetPassword;
import com.example.userservice.entity.vo.UserVo;
import com.example.userservice.mapper.UserMapper;
import com.example.userservice.permission.PermissionChecker;
import com.example.userservice.permission.PermissionCheckerFactory;
import com.example.userservice.service.UserService;
import com.example.userservice.util.JwtUtil;
import com.example.userservice.util.LogHelper;

import com.example.userservice.util.SnowflakeKeyGenerator;
import com.example.userservice.util.UserConverter;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import com.example.userservice.feign.PermissionFeign;
import org.springframework.util.StringUtils;


import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private LogHelper logHelper;
    @Autowired
    private PermissionFeign permissionFeign;
    @Autowired
    private PermissionCheckerFactory permissionCheckerFactory;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    SnowflakeKeyGenerator snowflakeKeyGenerator;

    //获取用户列表
    @Override
    public List<UserVo> getUsers() {
        Long currentUserId = UserContext.get().getUserId();

        String roleCode = Optional.ofNullable(permissionFeign.getUserRoleCode(currentUserId))
                .map(res -> res.getData())
                .orElseThrow(() -> new RuntimeException("获取用户角色失败"));

        PermissionChecker permissionChecker = permissionCheckerFactory.getPermissionChecker(roleCode);

        List<UserVo> result = permissionChecker.getUsers(currentUserId);
        if (result == null || result.isEmpty()) {
            throw new RuntimeException("非法权限");
        }

        return result;
    }
    //获取指定用户
    @Override
    public UserVo getUser(Long targetUserId) {
        Long currentUserId = UserContext.get().getUserId();
        System.out.println(currentUserId+"\\||\\"+targetUserId);
        String roleCode = Optional.ofNullable(permissionFeign.getUserRoleCode(currentUserId))
                .map(res -> res.getData())
                .orElseThrow(() -> new RuntimeException("获取用户角色失败"));

        PermissionChecker permissionChecker = permissionCheckerFactory.getPermissionChecker(roleCode);
        UserVo result = permissionChecker.getUser(currentUserId, targetUserId);
        if (result == null) {
            throw new RuntimeException("非法权限");
        }
        return result;
    }
    //修改指定用户信息
    @Override
    public Boolean updateUser(UserDtoUpdate user, Long targetUserId, String ip) {
        if (!StringUtils.hasText(user.getEmail()) || !StringUtils.hasText(user.getPhone())) {
            throw new RuntimeException("用户名或密码不能为空");
        }
        Long currentUserId = UserContext.get().getUserId();
        //当前用户信息即旧信息
        User currentUser = userMapper.selectById(currentUserId);
        //目标修改信息即新信息
        User targetUser = UserConverter.getUserFromUserDtoUpdate(user);

        String roleCode = Optional.ofNullable(permissionFeign.getUserRoleCode(currentUserId))
                .map(res -> res.getData())
                .orElseThrow(() -> new RuntimeException("获取用户角色失败"));

        PermissionChecker permissionChecker = permissionCheckerFactory.getPermissionChecker(roleCode);
        Boolean result =  permissionChecker.updateUser(currentUserId, targetUserId, targetUser);
        if (!result) {
            throw new RuntimeException("非法权限");
        }

        List<Detail> changes = logHelper.compareUserChanges(currentUser, targetUser);
        if (!changes.isEmpty()) {
            Log log = logHelper.buildFieldLog(currentUserId, "update_user", ip, changes);
            logHelper.printLog(log);
        }

        return result;
    }
    //修改指定用户密码
    @Override
    public Boolean resetPassword(UserDtoRetPassword user, String ip) {
        if (!StringUtils.hasText(user.getUserName()) || !StringUtils.hasText(user.getPassword())) {
            throw new RuntimeException("用户名或密码不能为空");
        }
        Long currentUserId = UserContext.get().getUserId();
        //获取目标用户原始密码
        String targetPassword = userMapper.selectPasswordByUserName(user.getUserName());
        Long targetUserId = userMapper.selectUserIdByUserName(user.getUserName());
        if (targetUserId == null) {
            throw new RuntimeException("目标用户不存在");
        }

        String roleCode = Optional.ofNullable(permissionFeign.getUserRoleCode(currentUserId))
                .map(res -> res.getData())
                .orElseThrow(() -> new RuntimeException("获取用户角色失败"));
        User targetUser = UserConverter.getUserFromUserDtoResetPassword(user);
        System.out.println(targetUserId+"\\||\\"+currentUserId+"\\||\\"+roleCode);
        PermissionChecker permissionChecker = permissionCheckerFactory.getPermissionChecker(roleCode);
        Boolean result =  permissionChecker.resetPassword(currentUserId, targetUser);
        if (!result) {
            throw new RuntimeException("非法权限");
        }
        targetUser.setUserId(targetUserId);
        Log log = logHelper.buildLog(targetUser.getUserId(),"password reset",ip,new Detail("password",targetPassword,user.getPassword()));
        logHelper.printLog(log);
        return result;
    }

    //注册
    @Override
    public void register(User user, String ip) {
        if (!StringUtils.hasText(user.getUserName()) || !StringUtils.hasText(user.getPassword())) {
            throw new RuntimeException("用户名或密码不能为空");
        }
        if (lambdaQuery().eq(User::getUserName, user.getUserName()).one() != null) {
            throw new RuntimeException("用户名已注册");
        }
        user.setUserId(snowflakeKeyGenerator.generateId());
        Message<User> message = MessageBuilder.withPayload(user)
                .setHeader("ip", ip)
                .build();

        rocketMQTemplate.sendMessageInTransaction(
                "register-topic", // topic
                message,
                user
        );
    }

    //登录
    @Override
    public String login(UserDtoRegisterOrLogin userDto, String ip) {
        try {
            if (!StringUtils.hasText(userDto.getUserName()) || !StringUtils.hasText(userDto.getPassword())) {
                throw new RuntimeException("用户名或密码不能为空");
            }
            User user = lambdaQuery().eq(User::getUserName, userDto.getUserName()).one();
            if (user == null || !user.getPassword().equals(userDto.getPassword())) {
                throw new RuntimeException("用户名或密码错误");
            }

            String token = JwtUtil.generateToken(user.getUserName(), user.getUserId());
            if (StringUtils.isEmpty(token)) {
                throw new RuntimeException("生成token失败");
            }

            Log logObj = logHelper.buildLog(user.getUserId(), "login", ip, userDto);
            logHelper.printLog(logObj);

            return token;
        } catch (Exception e) {
            log.error("登录异常");
            throw e;
        }
    }

}
